#pragma once

#include "Acceptor.h"
#include "EventLoop.h"
#include "InetAddress.h"
#include "TcpConnection.h"
#include <functional>
#include <memory>
#include <mutex>
#include <vector>

namespace GiSo {

// 对TCPServer的操作应该在主线程中进行
class TcpServer {
public:
    /**
     * @brief 构造一个新的 TcpServer 对象
     *
     * @param addr 服务器的地址
     * @param threadNum 额外的工作线程数量（不能小于1）
     */
    TcpServer(const InetAddress& addr, int threadNum);
    ~TcpServer();

    /**
     * @brief 启动服务器
     */
    void Start();

    /**
     * @brief 停止服务器
     */
    void Stop();

    /**
     * @brief 关闭所有连接并停止服务器
     */
    void Close();

    /**
     * @brief 设置新连接的回调函数
     *
     * @param cb 新连接的回调函数
     */
    void SetNewConnectionCallback(std::function<bool(std::shared_ptr<TcpConnection>, const InetAddress&)> cb);

    /**
     * @brief 设置关闭连接的回调函数
     *
     * @param cb 关闭连接的回调函数
     */
    void SetCloseConnectionCallback(std::function<void(std::shared_ptr<TcpConnection>)> cb);

private:
    int GetMinConnectionThread();
    void AddConnection(int id, int threadId, std::shared_ptr<TcpConnection> conn);
    void RemoveConnection(int id);

    std::unordered_map<int, std::pair<int, std::shared_ptr<TcpConnection>>> m_Connections;   // fd -> <threadId, conn>
    std::vector<int> m_EachThreadConnectionCount;                        // 每个线程负责的连接数
    std::unique_ptr<Acceptor> m_Acceptor;
    EventLoop m_EventLoop;

    std::function<bool(std::shared_ptr<TcpConnection>, const InetAddress&)> m_NewConnectionCallback; // 自行在 callback 里开启听或读
    std::function<void(std::shared_ptr<TcpConnection>)> m_CloseConnectionCallback;
    InetAddress m_Address;
    bool m_Running;

    std::mutex m_Mutex;
};

}